package com.wsh.crawler.service.impl.parser;


import com.wsh.crawler.constant.LanguageEnum;
import com.wsh.crawler.constant.NewsSourceEnum;
import com.wsh.crawler.entity.News;
import io.github.bonigarcia.wdm.WebDriverManager;
import jakarta.annotation.PostConstruct;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

public class Ligue1Parser extends AbstractNewsParser {

    private static final Logger LOGGER = LoggerFactory.getLogger(Ligue1Parser.class);

    public Ligue1Parser() {
        super(NewsSourceEnum.LIGUE_1.getName());
    }

    @PostConstruct
    public void init() {
        WebDriverManager.chromedriver().setup();
        LOGGER.info("【法甲解析】Selenium WebDriver 初始化完成");
    }

    @Override
    public List<String> parseArticleLinks(Document doc) {
        LOGGER.info("【法甲解析】开始解析新闻链接 - ligue1.com");
        return parseArticleLinksWithSelenium();
    }

    /**
     * 使用Selenium解析文章链接
     */
    private List<String> parseArticleLinksWithSelenium() {
        WebDriver driver = null;
        try {
            ChromeOptions options = createChromeOptions();
            driver = new ChromeDriver(options);
            driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(30));

            // 访问文章列表页面
            String listUrl = "https://ligue1.com/articles?competition=ligue1mcdonalds";
            LOGGER.info("【法甲解析】访问文章列表页：{}", listUrl);
            driver.get(listUrl);

            // 等待动态内容加载
            Thread.sleep(8000);

            // 解析渲染后的HTML
            Document doc = Jsoup.parse(driver.getPageSource());
            return extractLinksFromDocument(doc);

        } catch (Exception e) {
            LOGGER.error("【法甲解析】获取文章链接失败：{}", e.getMessage());
            return new ArrayList<>();
        } finally {
            if (driver != null) {
                try {
                    driver.quit();
                } catch (Exception e) {
                    LOGGER.warn("【法甲解析】关闭WebDriver失败", e);
                }
            }
        }
    }

    /**
     * 从文档中提取链接
     */
    private List<String> extractLinksFromDocument(Document doc) {
        List<String> links = new ArrayList<>();

        // 法甲文章链接选择器
        String[] selectors = {
                "a[href*='/articles/l1_article_']",    // 法甲文章链接
                "a[href*='/articles/']",               // 通用文章链接
                "a[href*='/en/articles/']",            // 英文文章链接
                ".article-card a",                     // 文章卡片
                ".news-item a",                        // 新闻项目
                ".card a[href*='article']",            // 文章卡片链接
                "[data-testid*='article'] a"          // 测试ID文章链接
        };

        for (String selector : selectors) {
            Elements elements = doc.select(selector);
            LOGGER.debug("【法甲解析】选择器 '{}' 找到 {} 个链接", selector, elements.size());

            for (Element link : elements) {
                String href = link.attr("href");
                if (!href.isEmpty()) {
                    String fullUrl = buildFullUrl(href);
                    if (isValidArticleUrl(fullUrl)) {
                        links.add(fullUrl);
                    }
                }
            }
        }

        List<String> uniqueLinks = links.stream().distinct().collect(Collectors.toList());
        LOGGER.info("【法甲解析】解析到 {} 个文章链接", uniqueLinks.size());
        return uniqueLinks;
    }

    @Override
    public News parseArticle(Document doc, String url) {
        LOGGER.info("【法甲解析】解析文章：{}", url);

        News article = new News();
        article.setSource(NewsSourceEnum.LIGUE_1.getName());
        article.setOriginalUrl(url);
        article.setCrawlTime(new Date());
        article.setLanguage(LanguageEnum.EN.getValue());

        parseTitle(doc, article);
        parseContent(article);
        parseMedia(doc, article);

        LOGGER.info("【法甲解析】解析完成：{}", article.getTitle());
        return article;
    }

    /**
     * 解析标题
     */
    private void parseTitle(Document doc, News article) {
        String[] selectors = {
                "h1",                                  // 主标题
                ".article-title",                      // 文章标题
                ".article-header h1",                  // 文章头部标题
                ".content-title",                      // 内容标题
                "title",                               // HTML标题
                "meta[property=og:title]"              // OG标题
        };

        for (String selector : selectors) {
            Element element = doc.selectFirst(selector);
            if (element != null) {
                String title = selector.startsWith("meta") ?
                        element.attr("content") : element.text();

                if (!title.trim().isEmpty()) {
                    // 清理标题
                    title = title.trim()
                            .replaceAll("\\s*-\\s*Ligue\\s*1.*$", "")
                            .replaceAll("\\s*\\|\\s*Ligue\\s*1.*$", "")
                            .trim();

                    if (title.length() > 10) {
                        article.setTitle(title);
                        LOGGER.info("【法甲解析】提取标题：{}", title);
                        return;
                    }
                }
            }
        }

        LOGGER.warn("【法甲解析】未能提取标题");
    }

    /**
     * 解析内容 - 使用Selenium
     */
    private void parseContent(News article) {
        WebDriver driver = null;
        try {
            ChromeOptions options = createChromeOptions();
            driver = new ChromeDriver(options);
            driver.manage().timeouts().pageLoadTimeout(Duration.ofSeconds(30));

            LOGGER.info("【法甲解析】访问文章页面：{}", article.getOriginalUrl());
            driver.get(article.getOriginalUrl());

            Thread.sleep(6000);

            Document doc = Jsoup.parse(driver.getPageSource());
            String content = extractContentFromDocument(doc);

            if (content != null && content.length() > 100) {
                article.setContent(cleanContent(content));
                LOGGER.info("【法甲解析】内容解析成功，长度：{}", content.length());
            } else {
                String pageText = doc.text();
                if (pageText.length() > 500) {
                    String summary = pageText.substring(0, Math.min(1000, pageText.length()));
                    article.setContent(cleanContent(summary) + "\n\n[内容概要，完整内容请查看原文]");
                    LOGGER.info("【法甲解析】使用页面概要");
                } else {
                    article.setContent("");
                    LOGGER.warn("【法甲解析】未能获取有效内容");
                }
            }

        } catch (Exception e) {
            LOGGER.error("【法甲解析】内容解析失败：{}", e.getMessage());
            article.setContent("");
        } finally {
            if (driver != null) {
                try {
                    driver.quit();
                } catch (Exception e) {
                    LOGGER.warn("【法甲解析】关闭WebDriver失败", e);
                }
            }
        }
    }

    /**
     * 从文档中提取内容
     */
    private String extractContentFromDocument(Document doc) {
        String[] contentSelectors = {
                ".article-content",
                ".article-body",
                ".content-body",
                ".post-content",
                ".entry-content",
                "main article",
                ".wysiwyg",
                "[data-testid*='content']",
                ".rich-text"
        };

        for (String selector : contentSelectors) {
            Element contentElement = doc.selectFirst(selector);
            if (contentElement != null) {
                String content = contentElement.text().trim();
                if (content.length() > 200) {
                    LOGGER.debug("【法甲解析】使用选择器 '{}' 找到内容", selector);
                    return content;
                }
            }
        }

        // 备用方案：通过段落提取
        Elements paragraphs = doc.select("p");
        StringBuilder content = new StringBuilder();

        for (Element p : paragraphs) {
            String pText = p.text().trim();
            if (pText.length() > 50 && !isUnwantedContent(pText)) {
                content.append(pText).append("\n\n");
                if (content.length() > 1500) {
                    break;
                }
            }
        }

        return content.length() > 200 ? content.toString() : null;
    }

    /**
     * 判断是否为不需要的内容
     */
    private boolean isUnwantedContent(String text) {
        String lowerText = text.toLowerCase();
        return lowerText.contains("cookie") ||
                lowerText.contains("privacy") ||
                lowerText.contains("legal notice") ||
                lowerText.contains("data protection") ||
                lowerText.contains("terms and conditions") ||
                text.length() < 30;
    }

    /**
     * 清理内容
     */
    private String cleanContent(String content) {
        return content
                .replaceAll("(?i)\\(photo[^)]*\\)", "")
                .replaceAll("(?i)\\(credit[^)]*\\)", "")
                .replaceAll("(?i)ligue1\\.com", "")
                .replaceAll("www\\.[\\w\\.]+", "")
                .replaceAll("\\n{3,}", "\n\n")
                .replaceAll("(?i)tune in at.*social media.*", "")
                .trim();
    }

    /**
     * 创建Chrome选项
     */
    private ChromeOptions createChromeOptions() {
        ChromeOptions options = new ChromeOptions();
        options.addArguments(
                "--headless",
                "--no-sandbox",
                "--disable-dev-shm-usage",
                "--disable-gpu",
                "--disable-images",
                "--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
        );
        return options;
    }

    /**
     * 解析媒体文件
     */
    private void parseMedia(Document doc, News article) {
        article.setImageUrls(extractImageUrls(doc));
        article.setVideoUrls(extractVideoUrls(doc));
        article.setCoverUrl(extractCoverImage(doc, article.getImageUrls()));
    }

    @Override
    public String extractCoverImage(Document doc, List<String> otherImageUrls) {
        Element ogImage = doc.selectFirst("meta[property=og:image]");
        if (ogImage != null && !ogImage.attr("content").isEmpty()) {
            return ogImage.attr("content");
        }

        Element twitterImage = doc.selectFirst("meta[name=twitter:image]");
        if (twitterImage != null && !twitterImage.attr("content").isEmpty()) {
            return twitterImage.attr("content");
        }

        return otherImageUrls.isEmpty() ? null : otherImageUrls.get(0);
    }

    @Override
    protected List<String> extractImageUrls(Document doc) {
        List<String> imageUrls = new ArrayList<>();

        String[] imageSelectors = {
                ".article-content img[src]",
                ".article-body img[src]",
                ".content-body img[src]",
                ".hero-image img[src]",
                "img[src]"
        };

        for (String selector : imageSelectors) {
            Elements images = doc.select(selector);
            for (Element img : images) {
                String src = img.attr("abs:src");
                if (isValidImageUrl(src)) {
                    imageUrls.add(src);
                }
            }
        }

        return imageUrls.stream().distinct().collect(Collectors.toList());
    }

    @Override
    protected List<String> extractVideoUrls(Document doc) {
        List<String> videoUrls = new ArrayList<>();

        Elements youtubeFrames = doc.select("iframe[src*=youtube], iframe[src*=youtu.be]");
        for (Element frame : youtubeFrames) {
            videoUrls.add(frame.attr("abs:src"));
        }

        Elements dailymotionFrames = doc.select("iframe[src*=dailymotion]");
        for (Element frame : dailymotionFrames) {
            videoUrls.add(frame.attr("abs:src"));
        }

        Elements videoElements = doc.select("video source[src]");
        for (Element source : videoElements) {
            videoUrls.add(source.attr("abs:src"));
        }

        return videoUrls.stream().distinct().collect(Collectors.toList());
    }

    /**
     * 构建完整URL
     */
    private String buildFullUrl(String href) {
        if (href.startsWith("http")) return href;
        return href.startsWith("/") ?
                "https://ligue1.com" + href :
                "https://ligue1.com/" + href;
    }

    /**
     * 判断是否为有效文章URL
     */
    private boolean isValidArticleUrl(String url) {
        return url.contains("ligue1.com") &&
                url.contains("/articles/") &&
                !url.contains("javascript:") &&
                !url.contains("#") &&
                !url.contains("?tab=") &&
                !url.contains("transfer-news"); // 排除转会新闻汇总页
    }

    /**
     * 验证图片URL有效性
     */
    private boolean isValidImageUrl(String src) {
        if (src == null || src.length() < 20) {
            return false;
        }

        String lower = src.toLowerCase();
        return (lower.contains(".jpg") || lower.contains(".jpeg") ||
                lower.contains(".png") || lower.contains(".webp")) &&
                !lower.contains("logo") && !lower.contains("icon") &&
                !lower.contains("avatar") && !lower.contains("placeholder");
    }
}